package pl.shenlon.ga;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import pl.shenlon.poker.game.PlayerActionType;

public class BehaviourPattern {
	public static final int POSITION_CHECK = 0, POSITION_RAISE = 1,
			POSITION_FOLD = 2, POSITION_CALL = 3, POSITION_BLUFF = 4;

	public static final Map<PlayerActionType, Integer> POSITIONS;

	public static final Random rnd;

	static {
		rnd = new Random();
		POSITIONS = new HashMap<PlayerActionType, Integer>();
		POSITIONS.put(PlayerActionType.BLUFF, POSITION_BLUFF);
		POSITIONS.put(PlayerActionType.CALL, POSITION_CALL);
		POSITIONS.put(PlayerActionType.CHECK, POSITION_CHECK);
		POSITIONS.put(PlayerActionType.FOLD, POSITION_FOLD);
		POSITIONS.put(PlayerActionType.RAISE, POSITION_RAISE);

	}

	public static BehaviourPattern createRandomizedBehaviourPattern() {
		BehaviourPattern pattern = new BehaviourPattern();
		int genomLength = pattern.getLength(), max = genomLength * 20;
		for (int i = 0; i < genomLength; i++) {
			int value = rnd.nextInt(max + 1);
			max -= value;
			pattern.setValue(i, value);
		}
		return pattern;
	}

	private final int[] pattern;

	public BehaviourPattern() {
		pattern = new int[5];
	}

	public BehaviourPattern(BehaviourPattern pattern) {
		this(pattern.getPattern());
	}

	public BehaviourPattern(int[] genom) {
		this.pattern = new int[genom.length];
		for (int i = 0; i < genom.length; i++) {
			this.pattern[i] = genom[i];
		}
	}

	@Override
	public boolean equals(Object other) {
		if (other != null && other instanceof BehaviourPattern) {
			BehaviourPattern that = (BehaviourPattern) other;
			for (int i = 0; i < pattern.length; i++) {
				if (pattern[i] != that.pattern[i]) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	public PlayerActionType getAction(PlayerActionType... allowedActionTypes) {
		int sum = getSum(allowedActionTypes);
		int val = rnd.nextInt(sum + 1);
		sum = 0;
		for (PlayerActionType type : allowedActionTypes) {
			sum += pattern[POSITIONS.get(type)];
			if (sum >= val) {
				return type;
			}
		}
		return null;
	}

	public PlayerActionType getActionTypeAtGenomIndex(int index) {
		switch (index) {
			case POSITION_BLUFF :
				return PlayerActionType.BLUFF;
			case POSITION_CHECK :
				return PlayerActionType.CHECK;
			case POSITION_CALL :
				return PlayerActionType.CALL;
			case POSITION_FOLD :
				return PlayerActionType.FOLD;
			case POSITION_RAISE :
				return PlayerActionType.RAISE;
		}
		return null;
	}

	private int getArrayIndex(PlayerActionType searched,
			PlayerActionType... array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(searched)) {
				return i;
			}
		}
		return -1;
	}

	public int getBluffChance() {
		return pattern[POSITION_BLUFF];
	}

	public int getCallChance() {
		return pattern[POSITION_CALL];
	}

	public int getCheckChance() {
		return pattern[POSITION_CHECK];
	}

	public int getFoldChance() {
		return pattern[POSITION_FOLD];
	}

	public int getLength() {
		return pattern.length;
	}

	public int[] getPattern() {
		return pattern;
	}

	public int getRaiseChance() {
		return pattern[POSITION_RAISE];
	}

	public int getSum() {
		int sum = 0;
		for (int value : pattern) {
			sum += value;
		}
		return sum;
	}

	public int getSum(PlayerActionType... allowedActions) {
		int sum = 0;

		for (PlayerActionType actionType : allowedActions) {
			sum += pattern[POSITIONS.get(actionType)];
		}

		return sum;
	}

	public int getValue(int index) {
		return pattern[index];
	}

	public boolean isIndexAllowed(int index,
			PlayerActionType... allowedActionTypes) {
		if (getArrayIndex(getActionTypeAtGenomIndex(index), allowedActionTypes) >= 0) {
			return true;
		}
		return false;
	}

	public void setBluffChance(int chance) {
		pattern[POSITION_BLUFF] = chance;
	}

	public void setCallChance(int chance) {
		pattern[POSITION_CALL] = chance;
	}

	public void setCheckChance(int chance) {
		pattern[POSITION_CHECK] = chance;
	}

	public void setFoldChance(int chance) {
		pattern[POSITION_FOLD] = chance;
	}

	public void setRaiseChance(int chance) {
		pattern[POSITION_RAISE] = chance;
	}

	public void setValue(int index, int value) {
		pattern[index] = value;
	}

	@Override
	public String toString() {
		return java.util.Arrays.toString(pattern);
	}
}